import {findDOM, compareTwoVdom} from './react-dom/client'
// 这是一个更新队列
export let updateQueue = {
    isBatchingUpdate:false,// 这是一个是否皮联合更新的标识，默认是非批量的，是同步的
    updaters:new Set(),//更新的集合
    batchUpdate(){
        updateQueue.isBatchingUpdate = false
        for(const updater of updateQueue.updaters){
            updater.updateComponent()
        }
        updateQueue.updaters.clear()
    }
}
class Updater{
    // 每个更新器会保存一个组件类的实例
    constructor(classInstance){
        this.classInstance = classInstance
        // 用来存放更新状态
        this.pendingStates = []
        this.callbacks = []
    }
    flushCallback()
    {
        if(this.callbacks.length>0){
            this.callbacks.forEach((callback)=>callback())
            this.callbacks.length = 0
        }
    }    
    addState(partialState,callback){
        this.pendingStates.push(partialState)
        if(typeof callback === 'function'){
            this.callbacks.push(callback)
        }
        // 准备更新
        this.emitUpdate()
    }
    emitUpdate(){
        // 如果需要批量更新
        if(updateQueue.isBatchingUpdate){
            // 则不要直接更新组件，而是先把更新器添加到updaters里面去暂存
            updateQueue.updaters.add(this)
        }else {
            this.updateComponent()
        }
    }
    updateComponent(){
        // 获取等生效状态数组和类的实例
        const {pendingStates,classInstance} = this
        // 如果有正在等待的状态
        if(pendingStates.length>0){
            shouldUpdate(classInstance,this.getState())
        }
    }
    // 获取新状态
    getState(){
        const {pendingStates,classInstance} = this
        // 先获取类的实例上的老状态udy
        let {state} = classInstance
        pendingStates.forEach((partialState)=>{
            if(typeof partialState === 'function'){
                partialState = partialState(state)
            }
            state={...state,...partialState}
        })
        pendingStates.length = 0
        return state
    }
    
}

function shouldUpdate(classInstancce,nextState){
    // 先把计算得到的新状态赋给类的实例
    classInstancce.state = nextState;
    // 让组件强制刷新
    classInstancce.forceUpdate()
}

export class Component{
    // 给嘞component添加一个静态属性 isReactComponent
    static isReactComponent = true
    constructor(props){
        this.props = props
        this.state = {}
        // 每一个类会有一个更新器的实例
        this.updater = new Updater(this)
    }
    setState(partialState,callback){
        this.updater.addState(partialState,callback)
    }
    forceUpdate(){
        // 先获取老的虚拟dom，再计算新的虚拟dom，找到新老虚拟DOM的差异，把这些差异跟新到真实DOM上
        // 获取老的虚拟DOM div#counter
        let oldRenderVdom = this.oldRenderVdom
        // 根据新的状态计算新的虚拟dom
        let newRenderVdom = this.render()
        // 获取到此组件对应的老的真实DOM, DIV 这里需要在DOM实现的时候挂载在虚拟dom中才行
        const oldDOM = findDOM(oldRenderVdom)
        // 比较新旧的虚拟DOM的差异，把更新后的结果放在真实DOM上
        compareTwoVdom(oldDOM.parentNode,oldRenderVdom,newRenderVdom)
        // 在更新后需要把oldRenderVdom更新为新的newRenderVdom
        // 第一次挂载，老的div#counter
        // 第一次更新的时候 新的div#counter
        // replaceChild div#root>新的div#counter
        // 它永远只想当前父DOM节点档期那的子DOM节点
        this.oldRenderVdom = newRenderVdom
        this.updater.flushCallback()
    }
}